package com.zxq.factory.encoder.impl;

import com.zxq.factory.encoder.IFieldEncoder;
import com.zxq.memory.ByteCombination;

public class DoubleFieldEncoder implements IFieldEncoder<Double> {


    /**
     * 将Double编码成8个字节
     * @param value
     * @param len
     * @return
     */
    LongFieldEncoder longFieldEncoder = new LongFieldEncoder();
    @Override
    public byte[] encoder(Double value, int len) {

        if(len != 8 ) {
            System.out.println("Double 只支持64");
            return null;
        }

        Double positiveValue = Math.abs(value);
        // 2的负几次方小于1
        Integer exponent = countExponent(positiveValue);
        //阶码 0.1111 移后 1.111
        //移码 保存方式
        Integer shiftFrame = 1023;
        //阶码 + 移码 保存方式
        Integer shiftCode = exponent + shiftFrame.intValue();
        //阶码的最后一位，会成为尾数的最高位，占1bit
        byte oneByte = (byte) (shiftCode / 16);
        byte twoByteHeadFour = (byte) (shiftCode % 16);
        if(value < 0) {
            //符号位小于零，最高位补1
            oneByte = (byte) (oneByte + 0xf0);
        }
        byte[] exponentBuff = new byte[]{oneByte};
        Double unitValue = value / Math.pow(2, exponent);

        Double tailNumber = (unitValue - 1) * Math.pow(2,52);

        byte[] longBuff =  longFieldEncoder.encoder(tailNumber.longValue(),7);
        longBuff[0] = (byte) (twoByteHeadFour * 16 + longBuff[0]);
        byte[] total = ByteCombination.combinationContent(exponentBuff,longBuff);

        // 0​​100 0000 0011​​ 0111 0100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1101​​
        //   4    0    3    7    4    c   c    c    c    c     c   c     c    c   c     D
        return total;
    }

    // param 0, return 1;  param 1,return 1;  param 2,return 1;  param 3, return 2
    // param 4, return 2;  param 5.return 3;  param 5,return 3;  param 7, return 3
    private  Integer countExponent(Double value) {

        /**
         * 从-1开始，最低单位是1
         */
        Integer exponent = 0;
        Double intUnit = 1.0;
        if(value > 1) {
            while (!((value / intUnit) > 1 && (value / intUnit) < 2)) {
                exponent ++;
                intUnit = Math.pow(2, exponent);
            }
        } else if(value == 1.0f){
            exponent = 0;
        } else {
            while ( !((value / intUnit) > 1 && (value / intUnit) < 2) ) {
                exponent --;
                intUnit = Math.pow(2, exponent);
            }
        }

        return exponent;
    }

//    public static void main(String[] args) {
//
//        Double dValue = 2.25;
//        DoubleFieldEncoder doubleFieldEncoder = new DoubleFieldEncoder();
//        byte[] hexBuff = doubleFieldEncoder.encoder(dValue,8);
//        log.info("index:"  + HexBin.encode(hexBuff) );
//    }

}
